package cn.b.sky.user;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.servlet.*;
import java.io.IOException;

@Service
public class MyFilterSecurityInterceptor extends FilterSecurityInterceptor implements Filter {

  @Autowired
  private FilterInvocationSecurityMetadataSource securityMetadataSource;

  @Autowired
  public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
    super.setAccessDecisionManager(myAccessDecisionManager);
  }

  // 登陆后，每次访问资源都通过这个拦截器拦截
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
          ServletException {
    FilterInvocation fi = new FilterInvocation(request, response, chain);
    invoke(fi);
  }

  public void invoke(FilterInvocation fi) throws IOException, ServletException {
    // fi里面有一个被拦截的url
    // 里面调用MyInvocationSecurityMetadataSource的getAttributes(Object
    // object)这个方法获取fi对应的所有权限
    // 再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
    InterceptorStatusToken token = super.beforeInvocation(fi);
    try {
      // 执行下一个拦截器
      fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    } finally {
      super.afterInvocation(token, null);
    }
  }

  public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
    return this.securityMetadataSource;
  }

  @Override
  public Class<?> getSecureObjectClass() {
    return FilterInvocation.class;
  }

  @Override
  public SecurityMetadataSource obtainSecurityMetadataSource() {
    return this.securityMetadataSource;
  }

  public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
    this.securityMetadataSource = newSource;
  }

  @Override
  public void destroy() {
    // Do noting
  }

  @Override
  public void init(FilterConfig arg0) throws ServletException {
    // Do noting
  }

}